package today.rocky.boot.redis.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @version 1.0
 * @vlog:
 * @description:
 * @author: Rocky
 * @createDate: 2020/6/2 16:54
 */
@Component
public class LimiterFilter implements Filter {

	@Autowired
	private RedisTemplate<String,Integer> redisTemplate;

	/**
	 * key过期时间（秒）
	 */
	private final Long EXPIRE_TIME = 60L;

	/**
	 * key 前缀，防止和其他地方的key可以冲突
	 */
	private final String PREFIX = "IP:";


	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException,
			ServletException {
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;

		// 获取请求IP
		String ip = request.getHeader("X-Forwarded-For");
		if (!StringUtils.isEmpty(ip) && !"unKnow".equalsIgnoreCase(ip)) {
			//多次反向代理后会有多个ip值，第一个ip才是真实ip
			String[] ipList1 = ip.split(",");
			ip = ipList1[0];
		} else {
			ip = request.getHeader("X-Real-IP");
			if (StringUtils.isEmpty(ip) || "unKnown".equalsIgnoreCase(ip)) {
				ip = request.getRemoteAddr();
			}
		}

		// 前缀+ip构成key
		String key = PREFIX+ip;
		//检查key是否存在，返回boolean值
		Boolean flag = redisTemplate.hasKey(key);
		if(flag!=null) {
			if (flag) {
				// 调用次数+1
				redisTemplate.boundValueOps(key).increment(1);
				// 设置过期时间
				redisTemplate.expire(ip, EXPIRE_TIME, TimeUnit.SECONDS);
				Integer sumVal = redisTemplate.opsForValue().get(key);
				if (sumVal > 3) {
					System.out.println("第" + sumVal + "次请求，请求失败！");
					request.getRequestDispatcher("/errorPage").forward(request, response);
				}
			} else {
				// 第一次调用，所以value（调用次数）设置为1
				redisTemplate.opsForValue().set(key, 1, EXPIRE_TIME, TimeUnit.SECONDS);
			}
		}
		chain.doFilter(servletRequest, servletResponse);
	}
}
